﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;

namespace MyLibrary.Tools
{
    public class SoundPlayer
    {
        public SoundPlayer()
        {
        }

        //定义API函数
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        private string _name = String.Empty;
        [MarshalAs(UnmanagedType.ByValTStr,SizeConst = 128)]
        private string _length = String.Empty;
        [MarshalAs(UnmanagedType.LPTStr,SizeConst = 128)]
        private string _tempStr = String.Empty;

        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        private extern static int GetShortPathName(string lpszLongPath, string shortFile, int cchBuffer);
        [DllImport("winmm.dll", EntryPoint="mciSendString", CharSet = CharSet.Auto)]
        private extern static int mciSendString(string lpstrCommand, string lpstrReturnString, int uReturnLength, int hwndCallback);
        [DllImport("winmm.dll", CharSet = CharSet.Auto)]
        private static extern bool PlaySound([MarshalAs(UnmanagedType.LPWStr)] string soundName, IntPtr hmod, int soundFlags);

        int _long;
        bool _repeat = false;
        PlayState _state = PlayState.Stop;

        public PlayState State
        {
            get { return _state; }
        }
        /// <summary>
        /// 播放状态
        /// </summary>
        public enum PlayState
        {
            Playing = 1,
            Pause = 2,
            Stop = 3,
            Looping = 4
        }

        public struct MCI
        {
            public bool Mut;
            public int Dur;
            public int Pos;
            public int Vol;
            public int Bal;
            public string Name;
            public PlayState State;
        }

        MCI mci = new MCI();

        private string _wavFile = String.Empty;
        public string WavFile
        {
            get { return _wavFile; }
            set
            {
                if (!File.Exists(value)) throw new FileNotFoundException("指定的文件未找到");
                FileInfo fi = new FileInfo(value);
                if (fi.Extension != ".wav") throw new FormatException("必须是Wav文件");

                this._wavFile = value;
            }
        }

        public string FileName
        {
            get
            {
                return mci.Name;
            }
            set
            {
                try
                {
                    _tempStr = String.Empty;
                    _tempStr = _tempStr.PadLeft(127, Convert.ToChar(" "));
                    _name = String.Empty;
                    _name = _name.PadLeft(260, Convert.ToChar(" "));
                    mci.Name = value;
                    _long = GetShortPathName(mci.Name, _name, _name.Length);
                    _name = GetCurrentPath(_name);

                    _name = "open " + Convert.ToChar(34) + _name + Convert.ToChar(34) + " alias media";
                    _long = mciSendString("close all", _tempStr, _tempStr.Length, 0);
                    _long = mciSendString(_name, _tempStr, _tempStr.Length, 0);
                    _long = mciSendString("set media time format milliseconds", _tempStr, _tempStr.Length, 0);
                    mci.State = PlayState.Stop;
                }
                catch(Exception ex)
                {
                    throw new ArgumentException("获取文件名错误" + ex.Message);
                }
            }
        }

        public int Duration
        {
            get
            {
                _length = String.Empty;
                _length = _length.PadLeft(128, Convert.ToChar(" "));
                mciSendString("Status media length", _length, _length.Length, 0);
                _length = _length.Trim();

                if (String.IsNullOrEmpty(_length)) return 0;
                return (int)(Convert.ToDouble(_length) / 1000f);
            }
        }

        public int CurrentPosition
        {
            get
            {
                _length = String.Empty;
                _length = _length.PadLeft(128, Convert.ToChar(" "));
                mciSendString("status media position", _length, _length.Length, 0);
                mci.Pos = (int)(Convert.ToDouble(_length) / 1000f);
                return mci.Pos;
            }
        }

        public bool Repeat
        {
            get { return _repeat; }
            set { _repeat = value; }
        }

        public void Play()
        {
            _tempStr = String.Empty;
            _tempStr = _tempStr.PadLeft(127, Convert.ToChar(" "));
            mciSendString("play media", _tempStr, _tempStr.Length, 0);
            mci.State = PlayState.Playing;
        }

        public void Stop()
        {
            _tempStr = String.Empty;
            _tempStr = _tempStr.PadLeft(128, Convert.ToChar(" "));
            _long = mciSendString("close media", _tempStr, 128, 0);
            _long = mciSendString("close all", _tempStr, 128, 0);
            mci.State = PlayState.Stop;
        }

        public void Pause()
        {
            _tempStr = String.Empty;
            _tempStr = _tempStr.PadLeft(128, Convert.ToChar(" "));
            _long = mciSendString("pause media", _tempStr, _tempStr.Length, 0);
            mci.State = PlayState.Pause;
        }

        public void PlayWavLoop()
        {
            if (_state != PlayState.Stop) return;

            if (String.IsNullOrEmpty(this._wavFile)) throw new ArgumentNullException("波形文件路径不能为空");
            PlaySound(this._wavFile, IntPtr.Zero, 2 | 9);
            _state = PlayState.Looping;
        }

        public void StopWavLoop()
        {
            if (_state != PlayState.Looping) return;

            PlaySound(null, IntPtr.Zero, 0x40);
            _state = PlayState.Stop;
        }

        private string GetCurrentPath(string name)
        {
            if (name.Length < 1) return String.Empty;
            name = name.Trim();
            name = name.Substring(0, name.Length - 1);
            return name;
        }

    }
}
